package biz.datalk.industrialland.admin.modules.system.service.impl;

import biz.datalk.industrialland.admin.component.shiro.CustomLoginUser;
import biz.datalk.industrialland.admin.modules.system.mapper.ISysRoleExtMapper;
import biz.datalk.industrialland.admin.modules.system.pojo.dto.SysRoleDTO;
import biz.datalk.industrialland.admin.modules.system.service.ISysRoleService;
import biz.datalk.industrialland.admin.modules.util.ShiroUtil;
import biz.datalk.industrialland.common.def.enums.DBYNEnum;
import biz.datalk.industrialland.common.exception.ServiceException;
import biz.datalk.industrialland.common.result.UnifyResult;
import biz.datalk.industrialland.common.util.EntityIdUtils;
import biz.datalk.industrialland.common.util.I18NUtil;
import biz.datalk.industrialland.mbg.mapper.SysRoleMapper;
import biz.datalk.industrialland.mbg.pojo.po.SysRole;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author tarofang@163.com
 * @date 2019-08-19
 */
@Slf4j
@Service
public class SysRoleServiceImpl implements ISysRoleService {

    private final SysRoleMapper sysRoleMapper;

    private final ISysRoleExtMapper sysRoleExtMapper;

    @Autowired
    public SysRoleServiceImpl(SysRoleMapper sysRoleMapper, ISysRoleExtMapper sysRoleExtMapper) {
        this.sysRoleMapper = sysRoleMapper;
        this.sysRoleExtMapper = sysRoleExtMapper;
    }

    @Override
    public UnifyResult list(SysRoleDTO sysRoleDTO) {

        QueryWrapper<SysRole> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc(SysRole.COL_UPDATE_TIME);
        queryWrapper.eq(SysRole.COL_IS_DELETE, DBYNEnum.N.name());
        queryWrapper.eq(SysRole.COL_IS_VALID, DBYNEnum.Y.name());
        if (StringUtils.isNotEmpty(sysRoleDTO.getRoleName())) {
            queryWrapper.like(SysRole.COL_ROLE_NAME, sysRoleDTO.getRoleName().trim());
        }
        if (StringUtils.isNotEmpty(sysRoleDTO.getRoleCode())) {
            queryWrapper.like(SysRole.COL_ROLE_CODE, sysRoleDTO.getRoleName().trim());
        }

        IPage<SysRole> page = new Page<>(sysRoleDTO.getPageNumber(), sysRoleDTO.getPageSize());
        IPage<SysRole> pageInfo = sysRoleMapper.selectPage(page, queryWrapper);

        return UnifyResult.success().mapData().put("rows", pageInfo.getRecords()).put("total", pageInfo.getTotal());
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    @Override
    public UnifyResult addRole(SysRoleDTO sysRoleDTO) {
        String roleCode = StringUtils.trimToEmpty(sysRoleDTO.getRoleCode());
        SysRole existsRoleCode = findRoleByRoleCode(roleCode);
        if (existsRoleCode != null) {
            return UnifyResult.fail(I18NUtil.getMsg("role.code.exists"));
        }

        Date now = new Date();
        CustomLoginUser customLoginUser = ShiroUtil.currentLoginUser();

        SysRole sysRole = new SysRole();
        sysRole.setRoleName(sysRoleDTO.getRoleName());
        sysRole.setRoleCode(roleCode);
        sysRole.setDescription(StringUtils.trimToEmpty(sysRoleDTO.getDescription()));
        sysRole.setIsValid(DBYNEnum.Y.name());
        sysRole.setIsDelete(DBYNEnum.N.name());
        sysRole.setCreateBy(customLoginUser.getId());
        sysRole.setCreateName(customLoginUser.getRealname());
        sysRole.setCreateTime(now);
        sysRole.setUpdateBy(0L);
        sysRole.setUpdateName(StringUtils.EMPTY);
        sysRole.setUpdateTime(now);
        sysRole.setSysOrgCode(StringUtils.EMPTY);

        sysRoleMapper.insertSelective(sysRole);
        return UnifyResult.success();
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    @Override
    public UnifyResult updateRole(SysRoleDTO sysRoleDTO) {
        SysRole sysRole = sysRoleMapper.selectById(sysRoleDTO.getId());
        if (sysRole == null) {
            return UnifyResult.fail(I18NUtil.getMsg("role.no.exists.or.delete"));
        }

        String roleCode = StringUtils.trimToEmpty(sysRoleDTO.getRoleCode());
        SysRole existsRoleCode = findRoleByRoleCode(roleCode);
        if (existsRoleCode != null && !existsRoleCode.getId().equals(sysRole.getId())) {
            return UnifyResult.fail(I18NUtil.getMsg("role.code.exists"));
        }

        Long currentUserId = ShiroUtil.getCurrentUserId();
        Date now = new Date();

        sysRole.setRoleCode(roleCode);
        sysRole.setRoleName(sysRoleDTO.getRoleName().trim());
        if (StringUtils.isNotBlank(sysRoleDTO.getDescription())) {
            sysRole.setDescription(StringUtils.trimToEmpty(sysRoleDTO.getDescription()));
        }
        String isDelete = sysRoleDTO.getIsDelete();
        if (StringUtils.isNotBlank(isDelete) && StringUtils.equalsAny(isDelete, DBYNEnum.Y.name(), DBYNEnum.N.name())) {
            sysRole.setIsDelete(isDelete);
        }
        String isValid = sysRoleDTO.getIsValid();
        if (StringUtils.isNotBlank(isValid) && StringUtils.equalsAny(isValid, DBYNEnum.Y.name(), DBYNEnum.N.name())) {
            sysRole.setIsValid(isValid);
        }
        if (StringUtils.isNotBlank(sysRoleDTO.getSysOrgCode())) {
            sysRole.setSysOrgCode(sysRoleDTO.getSysOrgCode().trim());
        }
        sysRole.setUpdateBy(currentUserId);
        sysRole.setUpdateTime(now);

        sysRoleMapper.updateByPrimaryKeySelective(sysRole);
        return UnifyResult.success();
    }

    @Override
    public SysRole findRoleByRoleCode(String roleCode) {
        if (StringUtils.isBlank(roleCode)) {
            return null;
        }

        QueryWrapper<SysRole> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(SysRole.COL_ROLE_CODE, roleCode.trim());
        List<SysRole> sysRoles = sysRoleMapper.selectList(queryWrapper);

        int size = CollectionUtils.size(sysRoles);
        if (size == 0) {
            return null;
        }

        if (size > 1) {
            throw new ServiceException(I18NUtil.getMsg("role.multiple.code"));
        }

        return sysRoles.get(0);
    }

    @Override
    public List<SysRole> findRoleListByRoleCode(String roleCode) {
        if (StringUtils.isBlank(roleCode)) {
            return null;
        }

        QueryWrapper<SysRole> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(SysRole.COL_ROLE_CODE, roleCode);
        return sysRoleMapper.selectList(queryWrapper);
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    @Override
    public UnifyResult batchDelete(SysRoleDTO sysRoleDTO) {
        List<Long> sysids = EntityIdUtils.parseIds(sysRoleDTO.getSysids());

        SysRole params = new SysRole();
        Long currentUserId = ShiroUtil.getCurrentUserId();
        params.setUpdateBy(currentUserId);
        params.setUpdateTime(new Date());
        params.setIsDelete(DBYNEnum.Y.name());
        params.setIsValid(DBYNEnum.N.name());

        UpdateWrapper<SysRole> updateWrapper = new UpdateWrapper<>();
        updateWrapper.in(SysRole.COL_ID, sysids);

        int resInt = sysRoleMapper.update(params, updateWrapper);
        if (resInt != CollectionUtils.size(sysids)) {
            throw new ServiceException(I18NUtil.getMsg("role.batch.delete.fail"));
        }

        return UnifyResult.success();
    }

    @Override
    public List<SysRole> allValidRoles() {
        QueryWrapper<SysRole> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(SysRole.COL_IS_DELETE, DBYNEnum.N.name());
        queryWrapper.eq(SysRole.COL_IS_VALID, DBYNEnum.Y.name());
        queryWrapper.orderByDesc(SysRole.COL_UPDATE_TIME);

        List<SysRole> userList = sysRoleMapper.selectList(queryWrapper);
        userList = userList == null ? new ArrayList<>() : userList;
        return userList;
    }

    @Override
    public SysRole selectById(Long roleId) {
        if (roleId <= 0L) {
            log.warn("Invalid roleId. [roleId={}]", roleId);
            return null;
        }
        return sysRoleMapper.selectById(roleId);
    }

}
